/*
 * Lucas McDaniel
 * GSoC '11
 * HoneyViz
 * 
 * 
 */

import java.awt.Color;
import java.util.ArrayList;
import java.util.Date;

public class SphereLocation {
    
    public ArrayList events;
    public Color paint;
    public double latitude, longitude;
    public int max;
    public String[] eventList;
    
    public double[][] rtnVals;
    
    public final double ratio = 0.001;
    public final double reduc = 1.0;
    public final double distance = 0.01;
    
    public SphereLocation(ArrayList events, double latitude, double longitude)
    {
        this.paint = Color.RED;
        this.events = events;
        this.latitude = latitude;
        this.longitude = longitude;
        max = 0;
    }
    
    public SphereLocation(DataElement DE, String[] eventList)
    {
        this.latitude = DE.latitude;
        this.longitude = DE.longitude;
        events = new ArrayList();
        events.add(DE);
        max = 0;
        this.eventList = eventList;
    }
    
    public void add(DataElement DE)
    {
        events.add(DE);
    }
    
    public int compareTo(DataElement DE)
    {
        if (DE.latitude != latitude)
            return latitude < DE.latitude ? -1 : 1;
        else if (DE.longitude != longitude)
            return longitude < DE.longitude ? -1 : 1;
        else
            return 0;
    }
    
    public void addMax(int max)
    {
        this.max = max;
    }
    
    public void makeLocs()
    {
        if (max <= 0)
        {
            return;
        }
        int counter = 0;
        ArrayList xList = new ArrayList();
        ArrayList yList = new ArrayList();
        for (int inc=0; inc<events.size(); inc++)
        {
            if (((DataElement)events.get(inc)).count > max * ratio)
            {
                counter++;
                xList.add(getX(inc));
                yList.add(getY(inc));
            }
        }
        if (counter == 0)
        {
            return;
        }
        ArrayList xRtnVal = new ArrayList();
        ArrayList yRtnVal = new ArrayList();
        int radius = 1;
        int counts = 6;
        while (counts <= eventList.length)
        {
            radius++;
            counts+=6*radius;
        }
        double scale = .75/(2*radius+1);
        for (int inc=0; inc<xList.size(); inc++)
        {
            boolean found1 = false;
            double tmp = ((DataElement)events.get(inc)).count/((double)max);
            double xVal1 = (Double)xList.get(inc);
            double yVal1 = (Double)yList.get(inc);
            if (tmp < distance)
            {
                continue;
            }
            for (int inc2=0; inc2<xList.size(); inc2++)
            {
                boolean found2 = false;
                if (inc!=inc2)
                {
                    double tmp2 = ((DataElement)events.get(inc2)).count/((double)max);
                    double xVal2 = xVal1 + (Double)xList.get(inc2) * scale;
                    double yVal2 = yVal1 + (Double)yList.get(inc2) * scale;
                    if (tmp2 < distance)
                    {
                        continue;
                    }
                    for (int inc3=0; inc3<xList.size(); inc3++)
                    {
                        if (inc3!=inc && inc3!=inc2)
                        {
                            found2 = true;
                            double tmp3 = ((DataElement)events.get(inc3)).count/((double)max);
                            double xVal3 = xVal2 + (Double)xList.get(inc3) * scale * tmp3 * scale;
                            double yVal3 = yVal2 + (Double)yList.get(inc3) * scale * tmp3 * scale;
                            if (tmp2 < distance)
                                continue;
                            xRtnVal.add(xVal3);
                            yRtnVal.add(yVal3);
                        }
                    }
                    if (!found2)
                    {
                        xRtnVal.add(xVal2);
                        yRtnVal.add(yVal2);
                    }
                }
            }
            if (!found1)
            {
                xRtnVal.add(xVal1);
                yRtnVal.add(yVal1);
            }
        }
        rtnVals = new double[xRtnVal.size()][2];
        for (int inc=0; inc<xRtnVal.size(); inc++)
        {
            rtnVals[inc][0] = (Double)xRtnVal.get(inc);
            rtnVals[inc][1] = (Double)yRtnVal.get(inc);
        }
    }
    
    public double getY(int val)
    {
        int rtnVal = 0;
        for (int inc=0; inc<eventList.length; inc++)
            if (eventList[inc].compareTo(((DataElement)events.get(val)).name)==0)
                rtnVal = inc;
        if (rtnVal == 0)
            return 0;
        int count = 6;
        int radius = 1;
        int offset = rtnVal;
        while (count < rtnVal)
        {
            offset-=radius*6;
            radius++;
            count+=radius*6;
        }
        return Math.cos((6.28*offset)/(6*radius))*radius;
    }
    
    public double getX(int val)
    {
        int rtnVal = 0;
        for (int inc=0; inc<eventList.length; inc++)
            if (eventList[inc].compareTo(((DataElement)events.get(val)).name)==0)
                rtnVal = inc;
        if (rtnVal == 0)
            return 0;
        int count = 6;
        int radius = 1;
        int offset = rtnVal;
        while (count < rtnVal)
        {
            offset-=radius*6;
            radius++;
            count+=radius*6;
        }
        return Math.sin((6.28*(offset))/(6*radius))*radius;
    }
    
    public String getName()
    {
        return LocationManager.getLocationName(latitude, longitude);
    }
    
    public EventColor createEventColorConversion()
    {
        return new EventColor(getName());
    }
    
    public DataElement createDataElementConversion()
    {
        return new DataElement(getName(), new Date(0), max, latitude, longitude);
    }
}
